@code-pushup/core 0.45.0 → 0.46.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/index.js +379 -376
  2. package/package.json +3 -3
package/index.js CHANGED
@@ -107,6 +107,7 @@ var fileNameSchema = z.string().trim().regex(filenameRegex, {
107
107
  }).min(1, { message: "file name is invalid" });
108
108
  var positiveIntSchema = z.number().int().positive();
109
109
  var nonnegativeIntSchema = z.number().int().nonnegative();
110
+ var nonnegativeNumberSchema = z.number().nonnegative();
110
111
  function packageVersionSchema(options) {
111
112
  const { versionDescription = "NPM version of the package", required } = options ?? {};
112
113
  const packageSchema = z.string({ description: "NPM package name" });
@@ -119,7 +120,7 @@ function packageVersionSchema(options) {
119
120
  { description: "NPM package name and version of a published package" }
120
121
  );
121
122
  }
122
- var weightSchema = nonnegativeIntSchema.describe(
123
+ var weightSchema = nonnegativeNumberSchema.describe(
123
124
  "Coefficient for the given score (use weight 0 if only for display)"
124
125
  );
125
126
  function weightedRefSchema(description, slugDescription) {
@@ -261,7 +262,7 @@ var tableObjectSchema = tableSharedSchema.merge(
261
262
  var tableSchema = (description = "Table information") => z4.union([tablePrimitiveSchema, tableObjectSchema], { description });
262
263
 
263
264
  // packages/models/src/lib/audit-output.ts
264
- var auditValueSchema = nonnegativeIntSchema.describe("Raw numeric value");
265
+ var auditValueSchema = nonnegativeNumberSchema.describe("Raw numeric value");
265
266
  var auditDisplayValueSchema = z5.string({ description: "Formatted value (e.g. '0.9 s', '2.1 MB')" }).optional();
266
267
  var auditDetailsSchema = z5.object(
267
268
  {
@@ -696,396 +697,114 @@ var reportsDiffSchema = z15.object({
696
697
  })
697
698
  );
698
699
 
699
- // packages/utils/src/lib/text-formats/constants.ts
700
- var NEW_LINE = "\n";
701
- var TAB = " ";
702
- var SPACE = " ";
703
-
704
- // packages/utils/src/lib/text-formats/html/details.ts
705
- function details(title, content, cfg = { open: false }) {
706
- return `<details${cfg.open ? " open" : ""}>${NEW_LINE}<summary>${title}</summary>${NEW_LINE}${// ⚠️ The blank line is needed to ensure Markdown in content is rendered correctly.
707
- NEW_LINE}${content}${NEW_LINE}${// @TODO in the future we could consider adding it only if the content ends with a code block
708
- // ⚠️ The blank line ensure Markdown in content is rendered correctly.
709
- NEW_LINE}</details>${// ⚠️ The blank line is needed to ensure Markdown after details is rendered correctly.
710
- NEW_LINE}`;
711
- }
712
-
713
- // packages/utils/src/lib/text-formats/html/font-style.ts
714
- var boldElement = "b";
715
- function bold(text) {
716
- return `<${boldElement}>${text}</${boldElement}>`;
717
- }
718
- var italicElement = "i";
719
- function italic(text) {
720
- return `<${italicElement}>${text}</${italicElement}>`;
700
+ // packages/utils/src/lib/diff.ts
701
+ function matchArrayItemsByKey({
702
+ before,
703
+ after,
704
+ key
705
+ }) {
706
+ const pairs = [];
707
+ const added = [];
708
+ const afterKeys = /* @__PURE__ */ new Set();
709
+ const keyFn = typeof key === "function" ? key : (item) => item[key];
710
+ for (const afterItem of after) {
711
+ const afterKey = keyFn(afterItem);
712
+ afterKeys.add(afterKey);
713
+ const match = before.find((beforeItem) => keyFn(beforeItem) === afterKey);
714
+ if (match) {
715
+ pairs.push({ before: match, after: afterItem });
716
+ } else {
717
+ added.push(afterItem);
718
+ }
719
+ }
720
+ const removed = before.filter(
721
+ (beforeItem) => !afterKeys.has(keyFn(beforeItem))
722
+ );
723
+ return {
724
+ pairs,
725
+ added,
726
+ removed
727
+ };
721
728
  }
722
- var codeElement = "code";
723
- function code(text) {
724
- return `<${codeElement}>${text}</${codeElement}>`;
729
+ function comparePairs(pairs, equalsFn) {
730
+ return pairs.reduce(
731
+ (acc, pair) => ({
732
+ ...acc,
733
+ ...equalsFn(pair) ? { unchanged: [...acc.unchanged, pair.after] } : { changed: [...acc.changed, pair] }
734
+ }),
735
+ {
736
+ changed: [],
737
+ unchanged: []
738
+ }
739
+ );
725
740
  }
726
741
 
727
- // packages/utils/src/lib/text-formats/html/link.ts
728
- function link(href, text) {
729
- return `<a href="${href}">${text || href}"</a>`;
730
- }
742
+ // packages/utils/src/lib/execute-process.ts
743
+ import { spawn } from "node:child_process";
731
744
 
732
- // packages/utils/src/lib/transform.ts
733
- function objectToEntries(obj) {
734
- return Object.entries(obj);
735
- }
736
- function deepClone(obj) {
737
- return obj == null || typeof obj !== "object" ? obj : structuredClone(obj);
738
- }
739
- function toUnixPath(path) {
740
- return path.replace(/\\/g, "/");
741
- }
742
- function capitalize(text) {
743
- return `${text.charAt(0).toLocaleUpperCase()}${text.slice(
744
- 1
745
- )}`;
746
- }
745
+ // packages/utils/src/lib/reports/utils.ts
746
+ import { join } from "node:path";
747
747
 
748
- // packages/utils/src/lib/table.ts
749
- function rowToStringArray({ rows, columns = [] }) {
750
- if (Array.isArray(rows.at(0)) && typeof columns.at(0) === "object") {
751
- throw new TypeError(
752
- "Column can`t be object when rows are primitive values"
753
- );
754
- }
755
- return rows.map((row) => {
756
- if (Array.isArray(row)) {
757
- return row.map(String);
758
- }
759
- const objectRow = row;
760
- if (columns.length === 0 || typeof columns.at(0) === "string") {
761
- return Object.values(objectRow).map(String);
762
- }
763
- return columns.map(
764
- ({ key }) => String(objectRow[key])
765
- );
766
- });
748
+ // packages/utils/src/lib/file-system.ts
749
+ import { bundleRequire } from "bundle-require";
750
+ import chalk2 from "chalk";
751
+ import { mkdir, readFile, readdir, rm, stat } from "node:fs/promises";
752
+
753
+ // packages/utils/src/lib/formatting.ts
754
+ function slugify(text) {
755
+ return text.trim().toLowerCase().replace(/\s+|\//g, "-").replace(/[^a-z\d-]/g, "");
767
756
  }
768
- function columnsToStringArray({ rows, columns = [] }) {
769
- const firstRow = rows.at(0);
770
- const primitiveRows = Array.isArray(firstRow);
771
- if (typeof columns.at(0) === "string" && !primitiveRows) {
772
- throw new Error("invalid union type. Caught by model parsing.");
757
+ function pluralize(text, amount) {
758
+ if (amount != null && Math.abs(amount) === 1) {
759
+ return text;
773
760
  }
774
- if (columns.length === 0) {
775
- if (Array.isArray(firstRow)) {
776
- return firstRow.map((_, idx) => String(idx));
777
- }
778
- return Object.keys(firstRow);
761
+ if (text.endsWith("y")) {
762
+ return `${text.slice(0, -1)}ies`;
779
763
  }
780
- if (typeof columns.at(0) === "string") {
781
- return columns.map(String);
764
+ if (text.endsWith("s")) {
765
+ return `${text}es`;
782
766
  }
783
- const cols = columns;
784
- return cols.map(({ label, key }) => label ?? capitalize(key));
767
+ return `${text}s`;
785
768
  }
786
- function getColumnAlignmentForKeyAndIndex(targetKey, targetIdx, columns = []) {
787
- const column = columns.at(targetIdx) ?? columns.find((col) => col.key === targetKey);
788
- if (typeof column === "string") {
789
- return column;
790
- } else if (typeof column === "object") {
791
- return column.align ?? "center";
792
- } else {
793
- return "center";
769
+ function formatBytes(bytes, decimals = 2) {
770
+ const positiveBytes = Math.max(bytes, 0);
771
+ if (positiveBytes === 0) {
772
+ return "0 B";
794
773
  }
774
+ const k = 1024;
775
+ const dm = decimals < 0 ? 0 : decimals;
776
+ const sizes = ["B", "kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"];
777
+ const i = Math.floor(Math.log(positiveBytes) / Math.log(k));
778
+ return `${Number.parseFloat((positiveBytes / Math.pow(k, i)).toFixed(dm))} ${sizes[i]}`;
795
779
  }
796
- function getColumnAlignmentForIndex(targetIdx, columns = []) {
797
- const column = columns.at(targetIdx);
798
- if (column == null) {
799
- return "center";
800
- } else if (typeof column === "string") {
801
- return column;
802
- } else if (typeof column === "object") {
803
- return column.align ?? "center";
804
- } else {
805
- return "center";
806
- }
780
+ function pluralizeToken(token, times) {
781
+ return `${times} ${Math.abs(times) === 1 ? token : pluralize(token)}`;
807
782
  }
808
- function getColumnAlignments({
809
- rows,
810
- columns = []
811
- }) {
812
- if (rows.at(0) == null) {
813
- throw new Error("first row can`t be undefined.");
814
- }
815
- if (Array.isArray(rows.at(0))) {
816
- const firstPrimitiveRow = rows.at(0);
817
- return Array.from({ length: firstPrimitiveRow.length }).map(
818
- (_, idx) => getColumnAlignmentForIndex(idx, columns)
819
- );
783
+ function formatDuration(duration) {
784
+ if (duration < 1e3) {
785
+ return `${duration} ms`;
820
786
  }
821
- const firstObject = rows.at(0);
822
- return Object.keys(firstObject).map(
823
- (key, idx) => getColumnAlignmentForKeyAndIndex(key, idx, columns)
824
- );
825
- }
826
-
827
- // packages/utils/src/lib/text-formats/html/table.ts
828
- function wrap(elem, content) {
829
- return `<${elem}>${content}</${elem}>${NEW_LINE}`;
830
- }
831
- function wrapRow(content) {
832
- const elem = "tr";
833
- return `<${elem}>${NEW_LINE}${content}</${elem}>${NEW_LINE}`;
787
+ return `${(duration / 1e3).toFixed(2)} s`;
834
788
  }
835
- function table(tableData) {
836
- if (tableData.rows.length === 0) {
837
- throw new Error("Data can't be empty");
838
- }
839
- const tableHeaderCols = columnsToStringArray(tableData).map((s) => wrap("th", s)).join("");
840
- const tableHeaderRow = wrapRow(tableHeaderCols);
841
- const tableBody = rowToStringArray(tableData).map((arr) => {
842
- const columns = arr.map((s) => wrap("td", s)).join("");
843
- return wrapRow(columns);
844
- }).join("");
845
- return wrap("table", `${NEW_LINE}${tableHeaderRow}${tableBody}`);
789
+ function formatDate(date) {
790
+ const locale = "en-US";
791
+ return date.toLocaleString(locale, {
792
+ weekday: "short",
793
+ month: "short",
794
+ day: "numeric",
795
+ year: "numeric",
796
+ hour: "numeric",
797
+ minute: "2-digit",
798
+ timeZoneName: "short"
799
+ }).replace(/\u202F/g, " ");
846
800
  }
847
801
 
848
- // packages/utils/src/lib/text-formats/md/font-style.ts
849
- var boldWrap = "**";
850
- function bold2(text) {
851
- return `${boldWrap}${text}${boldWrap}`;
852
- }
853
- var italicWrap = "_";
854
- function italic2(text) {
855
- return `${italicWrap}${text}${italicWrap}`;
856
- }
857
- var strikeThroughWrap = "~";
858
- function strikeThrough(text) {
859
- return `${strikeThroughWrap}${text}${strikeThroughWrap}`;
802
+ // packages/utils/src/lib/guards.ts
803
+ function isPromiseFulfilledResult(result) {
804
+ return result.status === "fulfilled";
860
805
  }
861
- var codeWrap = "`";
862
- function code2(text) {
863
- return `${codeWrap}${text}${codeWrap}`;
864
- }
865
-
866
- // packages/utils/src/lib/text-formats/md/headline.ts
867
- function headline(text, hierarchy = 1) {
868
- return `${"#".repeat(hierarchy)} ${text}${NEW_LINE}`;
869
- }
870
- function h(text, hierarchy = 1) {
871
- return headline(text, hierarchy);
872
- }
873
- function h1(text) {
874
- return headline(text, 1);
875
- }
876
- function h2(text) {
877
- return headline(text, 2);
878
- }
879
- function h3(text) {
880
- return headline(text, 3);
881
- }
882
- function h4(text) {
883
- return headline(text, 4);
884
- }
885
- function h5(text) {
886
- return headline(text, 5);
887
- }
888
- function h6(text) {
889
- return headline(text, 6);
890
- }
891
-
892
- // packages/utils/src/lib/text-formats/md/image.ts
893
- function image(src, alt) {
894
- return `![${alt}](${src})`;
895
- }
896
-
897
- // packages/utils/src/lib/text-formats/md/link.ts
898
- function link2(href, text) {
899
- return `[${text || href}](${href})`;
900
- }
901
-
902
- // packages/utils/src/lib/text-formats/md/list.ts
903
- function li(text, order = "unordered") {
904
- const style = order === "unordered" ? "-" : "- [ ]";
905
- return `${style} ${text}`;
906
- }
907
- function indentation(text, level = 1) {
908
- return `${TAB.repeat(level)}${text}`;
909
- }
910
-
911
- // packages/utils/src/lib/text-formats/md/paragraphs.ts
912
- function paragraphs(...sections) {
913
- return sections.filter(Boolean).join(`${NEW_LINE}${NEW_LINE}`);
914
- }
915
-
916
- // packages/utils/src/lib/text-formats/md/section.ts
917
- function section(...contents) {
918
- return `${lines(...contents)}${NEW_LINE}`;
919
- }
920
- function lines(...contents) {
921
- return `${contents.filter(Boolean).join(NEW_LINE)}`;
922
- }
923
-
924
- // packages/utils/src/lib/text-formats/md/table.ts
925
- var alignString = /* @__PURE__ */ new Map([
926
- ["left", ":--"],
927
- ["center", ":--:"],
928
- ["right", "--:"]
929
- ]);
930
- function tableRow(rows) {
931
- return `|${rows.join("|")}|`;
932
- }
933
- function table2(data) {
934
- if (data.rows.length === 0) {
935
- throw new Error("Data can't be empty");
936
- }
937
- const alignmentRow = getColumnAlignments(data).map(
938
- (s) => alignString.get(s) ?? String(alignString.get("center"))
939
- );
940
- return section(
941
- `${lines(
942
- tableRow(columnsToStringArray(data)),
943
- tableRow(alignmentRow),
944
- ...rowToStringArray(data).map(tableRow)
945
- )}`
946
- );
947
- }
948
-
949
- // packages/utils/src/lib/text-formats/index.ts
950
- var md = {
951
- bold: bold2,
952
- italic: italic2,
953
- strikeThrough,
954
- code: code2,
955
- link: link2,
956
- image,
957
- headline,
958
- h,
959
- h1,
960
- h2,
961
- h3,
962
- h4,
963
- h5,
964
- h6,
965
- indentation,
966
- lines,
967
- li,
968
- section,
969
- paragraphs,
970
- table: table2
971
- };
972
- var html = {
973
- bold,
974
- italic,
975
- code,
976
- link,
977
- details,
978
- table
979
- };
980
-
981
- // packages/utils/src/lib/diff.ts
982
- function matchArrayItemsByKey({
983
- before,
984
- after,
985
- key
986
- }) {
987
- const pairs = [];
988
- const added = [];
989
- const afterKeys = /* @__PURE__ */ new Set();
990
- const keyFn = typeof key === "function" ? key : (item) => item[key];
991
- for (const afterItem of after) {
992
- const afterKey = keyFn(afterItem);
993
- afterKeys.add(afterKey);
994
- const match = before.find((beforeItem) => keyFn(beforeItem) === afterKey);
995
- if (match) {
996
- pairs.push({ before: match, after: afterItem });
997
- } else {
998
- added.push(afterItem);
999
- }
1000
- }
1001
- const removed = before.filter(
1002
- (beforeItem) => !afterKeys.has(keyFn(beforeItem))
1003
- );
1004
- return {
1005
- pairs,
1006
- added,
1007
- removed
1008
- };
1009
- }
1010
- function comparePairs(pairs, equalsFn) {
1011
- return pairs.reduce(
1012
- (acc, pair) => ({
1013
- ...acc,
1014
- ...equalsFn(pair) ? { unchanged: [...acc.unchanged, pair.after] } : { changed: [...acc.changed, pair] }
1015
- }),
1016
- {
1017
- changed: [],
1018
- unchanged: []
1019
- }
1020
- );
1021
- }
1022
-
1023
- // packages/utils/src/lib/execute-process.ts
1024
- import { spawn } from "node:child_process";
1025
-
1026
- // packages/utils/src/lib/reports/utils.ts
1027
- import { join } from "node:path";
1028
-
1029
- // packages/utils/src/lib/file-system.ts
1030
- import { bundleRequire } from "bundle-require";
1031
- import chalk2 from "chalk";
1032
- import { mkdir, readFile, readdir, rm, stat } from "node:fs/promises";
1033
-
1034
- // packages/utils/src/lib/formatting.ts
1035
- function slugify(text) {
1036
- return text.trim().toLowerCase().replace(/\s+|\//g, "-").replace(/[^a-z\d-]/g, "");
1037
- }
1038
- function pluralize(text, amount) {
1039
- if (amount != null && Math.abs(amount) === 1) {
1040
- return text;
1041
- }
1042
- if (text.endsWith("y")) {
1043
- return `${text.slice(0, -1)}ies`;
1044
- }
1045
- if (text.endsWith("s")) {
1046
- return `${text}es`;
1047
- }
1048
- return `${text}s`;
1049
- }
1050
- function formatBytes(bytes, decimals = 2) {
1051
- const positiveBytes = Math.max(bytes, 0);
1052
- if (positiveBytes === 0) {
1053
- return "0 B";
1054
- }
1055
- const k = 1024;
1056
- const dm = decimals < 0 ? 0 : decimals;
1057
- const sizes = ["B", "kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"];
1058
- const i = Math.floor(Math.log(positiveBytes) / Math.log(k));
1059
- return `${Number.parseFloat((positiveBytes / Math.pow(k, i)).toFixed(dm))} ${sizes[i]}`;
1060
- }
1061
- function pluralizeToken(token, times) {
1062
- return `${times} ${Math.abs(times) === 1 ? token : pluralize(token)}`;
1063
- }
1064
- function formatDuration(duration) {
1065
- if (duration < 1e3) {
1066
- return `${duration} ms`;
1067
- }
1068
- return `${(duration / 1e3).toFixed(2)} s`;
1069
- }
1070
- function formatDate(date) {
1071
- const locale = "en-US";
1072
- return date.toLocaleString(locale, {
1073
- weekday: "short",
1074
- month: "short",
1075
- day: "numeric",
1076
- year: "numeric",
1077
- hour: "numeric",
1078
- minute: "2-digit",
1079
- timeZoneName: "short"
1080
- }).replace(/\u202F/g, " ");
1081
- }
1082
-
1083
- // packages/utils/src/lib/guards.ts
1084
- function isPromiseFulfilledResult(result) {
1085
- return result.status === "fulfilled";
1086
- }
1087
- function isPromiseRejectedResult(result) {
1088
- return result.status === "rejected";
806
+ function isPromiseRejectedResult(result) {
807
+ return result.status === "rejected";
1089
808
  }
1090
809
 
1091
810
  // packages/utils/src/lib/logging.ts
@@ -1262,10 +981,294 @@ async function importEsmModule(options) {
1262
981
  return mod.default;
1263
982
  }
1264
983
 
984
+ // packages/utils/src/lib/text-formats/constants.ts
985
+ var NEW_LINE = "\n";
986
+ var TAB = " ";
987
+ var SPACE = " ";
988
+
989
+ // packages/utils/src/lib/text-formats/html/details.ts
990
+ function details(title, content, cfg = { open: false }) {
991
+ return `<details${cfg.open ? " open" : ""}>${NEW_LINE}<summary>${title}</summary>${NEW_LINE}${// ⚠️ The blank line is needed to ensure Markdown in content is rendered correctly.
992
+ NEW_LINE}${content}${NEW_LINE}${// @TODO in the future we could consider adding it only if the content ends with a code block
993
+ // ⚠️ The blank line ensure Markdown in content is rendered correctly.
994
+ NEW_LINE}</details>${// ⚠️ The blank line is needed to ensure Markdown after details is rendered correctly.
995
+ NEW_LINE}`;
996
+ }
997
+
998
+ // packages/utils/src/lib/text-formats/html/font-style.ts
999
+ var boldElement = "b";
1000
+ function bold(text) {
1001
+ return `<${boldElement}>${text}</${boldElement}>`;
1002
+ }
1003
+ var italicElement = "i";
1004
+ function italic(text) {
1005
+ return `<${italicElement}>${text}</${italicElement}>`;
1006
+ }
1007
+ var codeElement = "code";
1008
+ function code(text) {
1009
+ return `<${codeElement}>${text}</${codeElement}>`;
1010
+ }
1011
+
1012
+ // packages/utils/src/lib/text-formats/html/link.ts
1013
+ function link(href, text) {
1014
+ return `<a href="${href}">${text || href}"</a>`;
1015
+ }
1016
+
1017
+ // packages/utils/src/lib/transform.ts
1018
+ function objectToEntries(obj) {
1019
+ return Object.entries(obj);
1020
+ }
1021
+ function deepClone(obj) {
1022
+ return obj == null || typeof obj !== "object" ? obj : structuredClone(obj);
1023
+ }
1024
+ function toUnixPath(path) {
1025
+ return path.replace(/\\/g, "/");
1026
+ }
1027
+ function capitalize(text) {
1028
+ return `${text.charAt(0).toLocaleUpperCase()}${text.slice(
1029
+ 1
1030
+ )}`;
1031
+ }
1032
+
1033
+ // packages/utils/src/lib/table.ts
1034
+ function rowToStringArray({ rows, columns = [] }) {
1035
+ if (Array.isArray(rows.at(0)) && typeof columns.at(0) === "object") {
1036
+ throw new TypeError(
1037
+ "Column can`t be object when rows are primitive values"
1038
+ );
1039
+ }
1040
+ return rows.map((row) => {
1041
+ if (Array.isArray(row)) {
1042
+ return row.map(String);
1043
+ }
1044
+ const objectRow = row;
1045
+ if (columns.length === 0 || typeof columns.at(0) === "string") {
1046
+ return Object.values(objectRow).map(String);
1047
+ }
1048
+ return columns.map(
1049
+ ({ key }) => String(objectRow[key])
1050
+ );
1051
+ });
1052
+ }
1053
+ function columnsToStringArray({ rows, columns = [] }) {
1054
+ const firstRow = rows.at(0);
1055
+ const primitiveRows = Array.isArray(firstRow);
1056
+ if (typeof columns.at(0) === "string" && !primitiveRows) {
1057
+ throw new Error("invalid union type. Caught by model parsing.");
1058
+ }
1059
+ if (columns.length === 0) {
1060
+ if (Array.isArray(firstRow)) {
1061
+ return firstRow.map((_, idx) => String(idx));
1062
+ }
1063
+ return Object.keys(firstRow);
1064
+ }
1065
+ if (typeof columns.at(0) === "string") {
1066
+ return columns.map(String);
1067
+ }
1068
+ const cols = columns;
1069
+ return cols.map(({ label, key }) => label ?? capitalize(key));
1070
+ }
1071
+ function getColumnAlignmentForKeyAndIndex(targetKey, targetIdx, columns = []) {
1072
+ const column = columns.at(targetIdx) ?? columns.find((col) => col.key === targetKey);
1073
+ if (typeof column === "string") {
1074
+ return column;
1075
+ } else if (typeof column === "object") {
1076
+ return column.align ?? "center";
1077
+ } else {
1078
+ return "center";
1079
+ }
1080
+ }
1081
+ function getColumnAlignmentForIndex(targetIdx, columns = []) {
1082
+ const column = columns.at(targetIdx);
1083
+ if (column == null) {
1084
+ return "center";
1085
+ } else if (typeof column === "string") {
1086
+ return column;
1087
+ } else if (typeof column === "object") {
1088
+ return column.align ?? "center";
1089
+ } else {
1090
+ return "center";
1091
+ }
1092
+ }
1093
+ function getColumnAlignments({
1094
+ rows,
1095
+ columns = []
1096
+ }) {
1097
+ if (rows.at(0) == null) {
1098
+ throw new Error("first row can`t be undefined.");
1099
+ }
1100
+ if (Array.isArray(rows.at(0))) {
1101
+ const firstPrimitiveRow = rows.at(0);
1102
+ return Array.from({ length: firstPrimitiveRow.length }).map(
1103
+ (_, idx) => getColumnAlignmentForIndex(idx, columns)
1104
+ );
1105
+ }
1106
+ const firstObject = rows.at(0);
1107
+ return Object.keys(firstObject).map(
1108
+ (key, idx) => getColumnAlignmentForKeyAndIndex(key, idx, columns)
1109
+ );
1110
+ }
1111
+
1112
+ // packages/utils/src/lib/text-formats/html/table.ts
1113
+ function wrap(elem, content) {
1114
+ return `<${elem}>${content}</${elem}>${NEW_LINE}`;
1115
+ }
1116
+ function wrapRow(content) {
1117
+ const elem = "tr";
1118
+ return `<${elem}>${NEW_LINE}${content}</${elem}>${NEW_LINE}`;
1119
+ }
1120
+ function table(tableData) {
1121
+ if (tableData.rows.length === 0) {
1122
+ throw new Error("Data can't be empty");
1123
+ }
1124
+ const tableHeaderCols = columnsToStringArray(tableData).map((s) => wrap("th", s)).join("");
1125
+ const tableHeaderRow = wrapRow(tableHeaderCols);
1126
+ const tableBody = rowToStringArray(tableData).map((arr) => {
1127
+ const columns = arr.map((s) => wrap("td", s)).join("");
1128
+ return wrapRow(columns);
1129
+ }).join("");
1130
+ return wrap("table", `${NEW_LINE}${tableHeaderRow}${tableBody}`);
1131
+ }
1132
+
1133
+ // packages/utils/src/lib/text-formats/md/font-style.ts
1134
+ var boldWrap = "**";
1135
+ function bold2(text) {
1136
+ return `${boldWrap}${text}${boldWrap}`;
1137
+ }
1138
+ var italicWrap = "_";
1139
+ function italic2(text) {
1140
+ return `${italicWrap}${text}${italicWrap}`;
1141
+ }
1142
+ var strikeThroughWrap = "~";
1143
+ function strikeThrough(text) {
1144
+ return `${strikeThroughWrap}${text}${strikeThroughWrap}`;
1145
+ }
1146
+ var codeWrap = "`";
1147
+ function code2(text) {
1148
+ return `${codeWrap}${text}${codeWrap}`;
1149
+ }
1150
+
1151
+ // packages/utils/src/lib/text-formats/md/headline.ts
1152
+ function headline(text, hierarchy = 1) {
1153
+ return `${"#".repeat(hierarchy)} ${text}${NEW_LINE}`;
1154
+ }
1155
+ function h(text, hierarchy = 1) {
1156
+ return headline(text, hierarchy);
1157
+ }
1158
+ function h1(text) {
1159
+ return headline(text, 1);
1160
+ }
1161
+ function h2(text) {
1162
+ return headline(text, 2);
1163
+ }
1164
+ function h3(text) {
1165
+ return headline(text, 3);
1166
+ }
1167
+ function h4(text) {
1168
+ return headline(text, 4);
1169
+ }
1170
+ function h5(text) {
1171
+ return headline(text, 5);
1172
+ }
1173
+ function h6(text) {
1174
+ return headline(text, 6);
1175
+ }
1176
+
1177
+ // packages/utils/src/lib/text-formats/md/image.ts
1178
+ function image(src, alt) {
1179
+ return `![${alt}](${src})`;
1180
+ }
1181
+
1182
+ // packages/utils/src/lib/text-formats/md/link.ts
1183
+ function link2(href, text) {
1184
+ return `[${text || href}](${href})`;
1185
+ }
1186
+
1187
+ // packages/utils/src/lib/text-formats/md/list.ts
1188
+ function li(text, order = "unordered") {
1189
+ const style = order === "unordered" ? "-" : "- [ ]";
1190
+ return `${style} ${text}`;
1191
+ }
1192
+ function indentation(text, level = 1) {
1193
+ return `${TAB.repeat(level)}${text}`;
1194
+ }
1195
+
1196
+ // packages/utils/src/lib/text-formats/md/paragraphs.ts
1197
+ function paragraphs(...sections) {
1198
+ return sections.filter(Boolean).join(`${NEW_LINE}${NEW_LINE}`);
1199
+ }
1200
+
1201
+ // packages/utils/src/lib/text-formats/md/section.ts
1202
+ function section(...contents) {
1203
+ return `${lines(...contents)}${NEW_LINE}`;
1204
+ }
1205
+ function lines(...contents) {
1206
+ return `${contents.filter(Boolean).join(NEW_LINE)}`;
1207
+ }
1208
+
1209
+ // packages/utils/src/lib/text-formats/md/table.ts
1210
+ var alignString = /* @__PURE__ */ new Map([
1211
+ ["left", ":--"],
1212
+ ["center", ":--:"],
1213
+ ["right", "--:"]
1214
+ ]);
1215
+ function tableRow(rows) {
1216
+ return `|${rows.join("|")}|`;
1217
+ }
1218
+ function table2(data) {
1219
+ if (data.rows.length === 0) {
1220
+ throw new Error("Data can't be empty");
1221
+ }
1222
+ const alignmentRow = getColumnAlignments(data).map(
1223
+ (s) => alignString.get(s) ?? String(alignString.get("center"))
1224
+ );
1225
+ return section(
1226
+ `${lines(
1227
+ tableRow(columnsToStringArray(data)),
1228
+ tableRow(alignmentRow),
1229
+ ...rowToStringArray(data).map(tableRow)
1230
+ )}`
1231
+ );
1232
+ }
1233
+
1234
+ // packages/utils/src/lib/text-formats/index.ts
1235
+ var md = {
1236
+ bold: bold2,
1237
+ italic: italic2,
1238
+ strikeThrough,
1239
+ code: code2,
1240
+ link: link2,
1241
+ image,
1242
+ headline,
1243
+ h,
1244
+ h1,
1245
+ h2,
1246
+ h3,
1247
+ h4,
1248
+ h5,
1249
+ h6,
1250
+ indentation,
1251
+ lines,
1252
+ li,
1253
+ section,
1254
+ paragraphs,
1255
+ table: table2
1256
+ };
1257
+ var html = {
1258
+ bold,
1259
+ italic,
1260
+ code,
1261
+ link,
1262
+ details,
1263
+ table
1264
+ };
1265
+
1265
1266
  // packages/utils/src/lib/reports/utils.ts
1266
1267
  var { image: image2, bold: boldMd } = md;
1267
1268
  function formatReportScore(score) {
1268
- return Math.round(score * 100).toString();
1269
+ const scaledScore = score * 100;
1270
+ const roundedScore = Math.round(scaledScore);
1271
+ return roundedScore === 100 && score !== 1 ? Math.floor(scaledScore).toString() : roundedScore.toString();
1269
1272
  }
1270
1273
  function formatScoreWithColor(score, options) {
1271
1274
  const styledNumber = options?.skipBold ? formatReportScore(score) : boldMd(formatReportScore(score));
@@ -2453,7 +2456,7 @@ var verboseUtils = (verbose = false) => ({
2453
2456
 
2454
2457
  // packages/core/package.json
2455
2458
  var name = "@code-pushup/core";
2456
- var version = "0.45.0";
2459
+ var version = "0.46.0";
2457
2460
 
2458
2461
  // packages/core/src/lib/implementation/execute-plugin.ts
2459
2462
  import chalk5 from "chalk";
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "@code-pushup/core",
3
- "version": "0.45.0",
3
+ "version": "0.46.0",
4
4
  "license": "MIT",
5
5
  "dependencies": {
6
- "@code-pushup/models": "0.45.0",
7
- "@code-pushup/utils": "0.45.0",
6
+ "@code-pushup/models": "0.46.0",
7
+ "@code-pushup/utils": "0.46.0",
8
8
  "@code-pushup/portal-client": "^0.7.0",
9
9
  "chalk": "^5.3.0"
10
10
  },